加密 Secrets 资源:Sealed Secrets 使用指南
Sealed Secrets是一种在版本控制中存储加密的Kubernetes秘密的解决方案。
在这篇博文中,我们将学习如何安装和使用它。
安装
Sealed Secrets 由两个部分组成:
- Client-side CLI tool: kubeseal
客户端CLI工具 kubeseal,用于加密机密和创建密封机密 - Server-side controller
服务器端控制器,用于解密 SealedSecret CRD 和 创建 secrets
controller 安装
添加仓库并将其安装到 kube-system 命名空间:
Repo=https://bitnami-labs.github.io/sealed-secrets
Chart=sealed-secrets
Target=sealed-secrets
NameSpace=kube-system
helm upgrade --install ${Target} ${Chart} \
--repo ${Repo} \
--namespace ${NameSpace} \
--create-namespace \
--set-string fullnameOverride=sealed-secrets-controller
# --set customKey=YOUR_CUSTOM_KEY_HERE
# key-renew-period=0
- --namespace
将其安装在
kube-systems
使得kubeseal命令不用显示声明--controller-namespace=kube-systems
- --set-string fullnameOverride=sealed-secrets-controller
这个参数会 kube-system 命名空间里创建 sealed-secrets-controller service 使得 kubeseal 命令不用显示声明
controller-name=sealed-secrets-controller
- 控制器在首次部署时会生成自己的证书,它还会为您管理续订。但您也可以自带证书,以便控制器也可以使用它们。
- 控制器使用任何标记为 sealedsecrets.bitnami.com/sealed-secrets-key=active 的密钥中包含的证书,该密钥必须与控制器位于同一命名空间中。可以有多个这样的秘密。
kubeseal 安装
kubeseal CLI 使用当前 kubectl 上下文访问集群。在继续之前,请确保 kubectl 已连接到应安装 Sealed Secrets 的群集。
# macos
brew install kubeseal
# linux
wget https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.13.1/kubeseal-linux-amd64 -O kubeseal
sudo install -m 755 kubeseal /usr/local/bin/kubeseal
工作原理
启动时,控制器会在其命名空间中搜索带有 sealedsecrets.bitnami.com/sealed-secrets-key 标签的 Secret 读取其中存放的私钥/公钥对。如果找不到,控制器则会生成一个新的 4096 位 RSA 密钥对,并在其命名空间中创建新的 Secret 将其保存其中。随后会将公钥部分打印到输出日志中。您可以使用以下命令以 YAML 格式查看此 Secret(包 含公有/私有密钥对)的内容:
kubectl get secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key -o yaml
配套的 CLI 工具 kubeseal 使用公钥加密 Secret 资源生成 SealedSecret 定制化资源定义 (CRD)we文件。将 SealedSecret 自定义资源部署到 Kubernetes 集群时,控制器会拾取该资源,然后使用私钥将其解封并创建一个 Secret 资源。加密和解密时会使用 SealedSecret 的命名空间/名称作为输入参数,这样可以确保 SealedSecret 和 Secret 严格绑定到相同的命名空间和名称。
kubeseal 可以通过 Kubernetes API 服务器与控制器进行通信,并在运行时检索加密 Secret 所需的公钥。您也可以从控制器下载公钥并保存在本地以便离线使用。
基础使用
SealedSecret 作用域
- SealedSecret 和 Secret 必须具有相同的命名空间和名称。此功能可防止同一集群上的其他用户重复使用您密封的密钥。
# 默认限制命名空间
kubeseal --format yaml < mysecret.yaml > mysealedsecret.yaml
# --scope 全局可用生成的密文可以在整个集群中使用,而不是仅限于特定的命名空间
kubeseal --format yaml --scope cluster-wide < mysecret.yaml > mysealedsecret2.yaml
加密 secret
kubeseal CLI 将 Kubernetes Secret 清单作为输入,对其进行加密并输出清单 SealedSecret 。
在本教程中,我们将使用此机密清单作为输入:
apiVersion: v1
kind: Secret
metadata:
creationTimestamp: null
name: my-secret
data:
password: YmFy
username: Zm9v
将清单存储在名为 secret.yaml and encrypt it 的文件中:
cat secret.yaml | kubeseal \
--controller-namespace kube-system \
--controller-name sealed-secrets \
--format yaml \
> sealed-secret.yaml
sealed-secret.yaml 文件的内容应如下所示:
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
creationTimestamp: null
name: my-secret
namespace: default
spec:
encryptedData:
password: AgA...
username: AgA...
template:
metadata:
creationTimestamp: null
name: my-secret
namespace: default
我们现在应该有秘密在里面 secret.yaml ,把密封的秘密在里面 sealed-secret.yaml 。此时已不再需要与该 Secret 有关的 YAML 清单,您可以将其删除。SealedSecret 将会是唯一被部署到集群的资源,如下所示:
请注意,原始 Secret 中的键(即username 和 password)在 SealedSecret 中未被加密,只有这些键对应的值被加密。您可以根据需要在 SealedSecret YAML 文件中更改这些键的名称,并且仍能够将更改后的键成功部署到集群中。但是,您不能更改 SealedSecret 的 name 和 namespace,否则会使 SealedSecret 无效,因为原始 Secret 的名称和命名空间会在加密过程中用作输入参数。这种方式提供了额外的保护措施,即使用户获得了对 SealedSecret 的 YAML 清单的访问权限(此 SealedSecret 是为在用户无权访问的 Kubernetes 集群中的特定命名空间而创建),他们也无法仅编辑清单和将 SealedSecret 部署到不同的命名空间(包括同一集群中的不同命名空间)。
为了部署密封的密钥,我们使用 kubectl 应用清单:
kubectl apply -f sealed-secret.yaml
集群中的控制器会注意到已创建资源 SealedSecret ,对其进行解密并创建已 Secret 解密的 .
让我们获取密钥以确保控制器已成功解封unsealed 它:
kubectl get secret my-secret -o yaml
数据应包含我们的 base64 编码用户名和密码:
...
data:
password: YmFy
username: Zm9v
...
一切都很顺利。秘密已被成功解封unsealed。
进阶指南
自定义密钥
export PRIVATEKEY="default.key"
export PUBLICKEY="default.crt"
export NAMESPACE="sealed-secrets"
export SECRETNAME="mycustomkeys"
export DAYS="3650"
生成新的 RSA 密钥对(证书)
openssl req -x509 -days ${DAYS} -nodes -newkey rsa:4096 -keyout "$PRIVATEKEY" -out "$PUBLICKEY" -subj "/CN=sealed-secret/O=sealed-secret"
使用您最近创建的 RSA 密钥对创建 tls k8s 密钥
kubectl -n "$NAMESPACE" create secret tls "$SECRETNAME" --cert="$PUBLICKEY" --key="$PRIVATEKEY"
kubectl -n "$NAMESPACE" label secret "$SECRETNAME" sealedsecrets.bitnami.com/sealed-secrets-key=active
需要删除控制器 Pod 才能选择新密钥
kubectl -n "$NAMESPACE" delete pod -l name=sealed-secrets-controller
查看控制器日志中的新证书(私钥)
kubectl -n "$NAMESPACE" logs -l name=sealed-secrets-controller
controller version: v0.12.1+dirty
2020/06/09 14:30:45 Starting sealed-secrets controller version: v0.12.1+dirty
2020/06/09 14:30:45 Searching for existing private keys
2020/06/09 14:30:45 ----- sealed-secrets-key5rxd9
2020/06/09 14:30:45 ----- mycustomkeys
2020/06/09 14:30:45 HTTP server serving on :8080
现在,您可以尝试使用自己的证书来密封密钥,而不是使用控制器提供的证书。
使用 --cert 以下标志使用自己的证书(密钥):
kubeseal --cert "./${PUBLICKEY}" --scope cluster-wide < mysecret.yaml | kubectl apply -f-
我们可以看到秘密已经成功解封
kubectl -n "$NAMESPACE" logs -l name=sealed-secrets-controller
controller version: v0.12.1+dirty
2020/06/09 14:30:45 Starting sealed-secrets controller version: v0.12.1+dirty
2020/06/09 14:30:45 Searching for existing private keys
2020/06/09 14:30:45 ----- sealed-secrets-key5rxd9
2020/06/09 14:30:45 ----- mycustomkeys
2020/06/09 14:30:45 HTTP server serving on :8080
2020/06/09 14:37:55 Updating test-namespace/mysecret
2020/06/09 14:37:55 Event(v1.ObjectReference{Kind:"SealedSecret", Namespace:"test-namespace", Name:"mysecret", UID:"f3a6c537-d254-4c06-b08f-ab9548f28f5b", APIVersion:"bitnami.com/v1alpha1", ResourceVersion:"20469957", FieldPath:""}): type: 'Normal' reason: 'Unsealed' SealedSecret unsealed successfully
PRIVATEKEY 是您的私钥,控制器使用它来解封您的密钥。不要与任何你不信任的人分享它,并将其保存在一个安全的地方!
导出公钥和加密
kubeseal --fetch-cert > public-key-cert.pem
然后使用 kubeseal 使用公钥文件创建 SealedSecret CRD,如下所示:
kubeseal --format=yaml --cert=public-key-cert.pem < secret.yaml > sealed-secret.yaml
导出私钥和解密
kubectl -n kube-system get secret -l sealedsecrets.bitnami.com/sealed-secrets-key=active -o yaml | kubectl neat > allsealkeys.yml
解密文件
kubectl get secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key -o yaml > sealed-secrets-key.yaml
kubeseal < sealed-secret.yaml --recovery-unseal --recovery-private-key sealed-secrets-key.yaml -o yaml
Conclusion 结论
Sealed Secrets 是一种在版本控制中管理 Kubernetes 机密的安全方法。在集群中存储加密密钥并解密机密。客户端无权访问加密密钥。
客户端使用 kubeseal CLI 工具生成 SealedSecret 保存加密数据的清单。应用文件后,服务器端控制器将识别新的密封密钥资源并对其进行解密以创建 Secret 资源。